import React, { createContext, useContext, useEffect, useRef, useState, useCallback } from 'react'

// WebSocket Context
const WebSocketContext = createContext(null)

// WebSocket Provider Component
export const WebSocketProvider = ({ children }) => {
  const [connected, setConnected] = useState(false)
  const [connectionStatus, setConnectionStatus] = useState('connecting') // connecting, connected, disconnected, error
  const [pendulumState, setPendulumState] = useState(null)
  const [angleHistory, setAngleHistory] = useState([])
  const [positionHistory, setPositionHistory] = useState([])
  const [backendLogs, setBackendLogs] = useState([])
  const [serialLogs, setSerialLogs] = useState([])
  
  const socketRef = useRef(null)
  const reconnectAttemptsRef = useRef(0)
  const reconnectTimeoutRef = useRef(null)
  const callbacksRef = useRef({
    onPendulumState: [],
    onAngleHistory: [],
    onPositionHistory: [],
    onLogs: [],
    onSerialLogs: [],
    onConnect: [],
    onDisconnect: [],
    onError: []
  })

  const config = {
    url: 'ws://127.0.0.1:5001',
    reconnectInterval: 2000,
    maxReconnectAttempts: 10
  }

  // 触发回调函数
  const triggerCallbacks = useCallback((event, data = null) => {
    if (callbacksRef.current[event]) {
      callbacksRef.current[event].forEach(callback => {
        try {
          callback(data)
        } catch (error) {
          console.error(`执行${event}回调时出错:`, error)
        }
      })
    }
  }, [])

  // 处理WebSocket消息
  const handleMessage = useCallback((data) => {
    const type = data.type
    
    switch (type) {
      case 'pendulum_state':
        setPendulumState(data.data)
        triggerCallbacks('onPendulumState', data.data)
        break
      case 'angle_history':
        setAngleHistory(data.data.history)
        triggerCallbacks('onAngleHistory', data.data.history)
        break
      case 'position_history':
        setPositionHistory(data.data.history)
        triggerCallbacks('onPositionHistory', data.data.history)
        break
      case 'logs':
        setBackendLogs(data.data.log)
        triggerCallbacks('onLogs', data.data.log)
        break
      case 'serial_logs':
        setSerialLogs(data.data.log)
        triggerCallbacks('onSerialLogs', data.data.log)
        break
      default:
        console.log('收到未知类型的WebSocket消息:', type, data)
    }
  }, [triggerCallbacks])

  // 安排重新连接
  const scheduleReconnect = useCallback(() => {
    if (reconnectAttemptsRef.current < config.maxReconnectAttempts) {
      reconnectAttemptsRef.current++
      console.log(`尝试重新连接 (${reconnectAttemptsRef.current}/${config.maxReconnectAttempts})...`)
      reconnectTimeoutRef.current = setTimeout(() => {
        connect()
      }, config.reconnectInterval)
    } else {
      console.error(`达到最大重连次数 (${config.maxReconnectAttempts})，停止重连`)
      setConnectionStatus('error')
    }
  }, [])

  // 连接WebSocket
  const connect = useCallback(() => {
    if (socketRef.current) {
      socketRef.current.close()
    }

    try {
      console.log(`正在连接WebSocket服务器: ${config.url}`)
      setConnectionStatus('connecting')
      
      const socket = new WebSocket(config.url)
      socketRef.current = socket

      socket.onopen = () => {
        console.log('WebSocket连接已建立')
        setConnected(true)
        setConnectionStatus('connected')
        reconnectAttemptsRef.current = 0
        triggerCallbacks('onConnect')
        
        // 连接成功后请求初始数据
        requestState()
        requestAngleHistory()
        requestPositionHistory()
        requestLogs()
        requestSerialLogs()
      }

      socket.onmessage = (event) => {
        try {
          const data = JSON.parse(event.data)
          handleMessage(data)
        } catch (error) {
          console.error('解析WebSocket消息失败:', error)
        }
      }

      socket.onclose = (event) => {
        console.log(`WebSocket连接已关闭，代码: ${event.code}, 原因: ${event.reason}`)
        setConnected(false)
        setConnectionStatus('disconnected')
        triggerCallbacks('onDisconnect')
        scheduleReconnect()
      }

      socket.onerror = (error) => {
        console.error('WebSocket错误:', error)
        setConnectionStatus('error')
        triggerCallbacks('onError', error)
      }
    } catch (error) {
      console.error('创建WebSocket连接失败:', error)
      setConnectionStatus('error')
      scheduleReconnect()
    }
  }, [handleMessage, triggerCallbacks, scheduleReconnect])

  // 发送消息
  const send = useCallback((message) => {
    if (!connected || !socketRef.current) {
      console.warn('WebSocket未连接，无法发送消息')
      return false
    }

    try {
      socketRef.current.send(JSON.stringify(message))
      return true
    } catch (error) {
      console.error('发送WebSocket消息失败:', error)
      return false
    }
  }, [connected])

  // API方法
  const requestState = useCallback(() => {
    return send({ command: 'get_state' })
  }, [send])

  const requestAngleHistory = useCallback(() => {
    return send({ command: 'get_angle_history' })
  }, [send])

  const requestPositionHistory = useCallback(() => {
    return send({ command: 'get_position_history' })
  }, [send])

  const requestLogs = useCallback(() => {
    return send({ command: 'get_log' })
  }, [send])

  const requestSerialLogs = useCallback(() => {
    return send({ command: 'get_serial_log' })
  }, [send])

  const sendKey = useCallback((key, extra = {}) => {
    return send({
      command: 'pendulum_key',
      key: key,
      ...extra
    })
  }, [send])

  const setHsv = useCallback((lower, upper) => {
    return send({
      command: 'set_hsv',
      lower: lower,
      upper: upper
    })
  }, [send])

  // 添加回调函数的方法
  const addCallback = useCallback((event, callback) => {
    if (callbacksRef.current[event]) {
      callbacksRef.current[event].push(callback)
    }
  }, [])

  // 移除回调函数的方法
  const removeCallback = useCallback((event, callback) => {
    if (callbacksRef.current[event]) {
      const index = callbacksRef.current[event].indexOf(callback)
      if (index > -1) {
        callbacksRef.current[event].splice(index, 1)
      }
    }
  }, [])

  // 关闭连接
  const close = useCallback(() => {
    if (reconnectTimeoutRef.current) {
      clearTimeout(reconnectTimeoutRef.current)
    }
    if (socketRef.current) {
      socketRef.current.close()
      socketRef.current = null
    }
    setConnected(false)
    setConnectionStatus('disconnected')
  }, [])

  // 初始化连接
  useEffect(() => {
    connect()
    
    return () => {
      close()
    }
  }, [])

  // 定期请求数据
  useEffect(() => {
    if (!connected) return

    const stateInterval = setInterval(() => {
      requestState()
    }, 100) // 每100ms请求一次状态更新

    const logInterval = setInterval(() => {
      requestLogs()
      requestSerialLogs()
    }, 1000) // 每1秒请求一次日志更新

    return () => {
      clearInterval(stateInterval)
      clearInterval(logInterval)
    }
  }, [connected, requestState, requestLogs, requestSerialLogs])

  const value = {
    // 状态
    connected,
    connectionStatus,
    pendulumState,
    angleHistory,
    positionHistory,
    backendLogs,
    serialLogs,
    
    // 方法
    send,
    requestState,
    requestAngleHistory,
    requestPositionHistory,
    requestLogs,
    requestSerialLogs,
    sendKey,
    setHsv,
    addCallback,
    removeCallback,
    connect,
    close
  }

  return (
    <WebSocketContext.Provider value={value}>
      {children}
    </WebSocketContext.Provider>
  )
}

// Hook for using WebSocket
export const useWebSocket = () => {
  const context = useContext(WebSocketContext)
  if (!context) {
    throw new Error('useWebSocket must be used within a WebSocketProvider')
  }
  return context
}
